# -*- coding: utf-8 -*-
import threading
import time
import serial
import socket
import ringbuffer

g_uart_name = "COM100"
g_serial = None
g_client = None
g_flag_quit = False
g_serv_host = "192.168.3.28"  # "127.0.0.1"
g_serv_port = 8080
g_uart_lock = threading.Lock()
g_net_lock = threading.Lock()
g_uart_ringBuffer = ringbuffer.RingBuffer(1024)
g_net_ringBuffer = ringbuffer.RingBuffer(1024)


def println(*args):
    current_time = time.time()
    print("[", current_time, "] ", end="")
    for arg in args:
        print(arg, end="")
    print("")


def get_uart_rb():
    return g_uart_ringBuffer.get()


def get_net_rb():
    return g_net_ringBuffer.get()


def set_net_info(host, port):
    global g_serv_host, g_serv_port
    g_serv_host = host
    g_serv_port = port


# str为16进制的格式如"313240410D0A"
def uart_send(dat):
    global g_flag_quit
    dat_type = type(dat)
    dat_out = ""
    if isinstance(dat, str):
        dat_out = bytes.fromhex(dat)
    elif isinstance(dat, bytes):
        dat_out = dat
    else:
        println("Unkown type: " + dat_type)
        return False
    ret = True
    try:
        g_uart_lock.acquire(timeout=0.5)
        g_serial.write(dat_out)
        ret = True
    except:
        g_flag_quit = True
        ret = False
    finally:
        g_uart_lock.release()
        return ret


def net_send(dat):
    global g_client
    ret = True
    if isinstance(dat, str):
        try:
            g_net_lock.acquire(timeout=0.5)
            g_client.send(dat.encode("utf-8"))
            ret = True
        except Exception as e:
            print("Exception: ", str(e))
            ret = False
        finally:
            g_net_lock.release()
            return ret
    else:
        try:
            g_net_lock.acquire(timeout=0.5)
            g_client.sendall(dat)
            ret = True
        except Exception as e:
            print("Exception: ", str(e))
            ret = False
        finally:
            g_net_lock.release()
            return ret


def serial_run(arg):
    global g_flag_quit
    println("uart [" + g_uart_name + "] thread is begin.")

    # g_serial.open()
    time.sleep(1.5)
    # uart_send_str("serial_begin testing...\r\n")
    total = 0
    while True:
        if g_flag_quit == True:
            break
        time.sleep(0.08)
        data = (bytes)(g_serial.read(100))  # 每包接收最大长度设置为N
        len_recv = len(data)
        if len_recv > 0:
            if data == b"exit":
                break
            for i in range(0, len_recv):
                g_uart_ringBuffer.append(data[i])
            total += len_recv
            # net_send(str(data))
            net_send(data)
            println("UART_RECV:", data.hex())
            println("U_len:", len_recv, "all:", total)
    g_serial.close()
    g_flag_quit = True
    println("uart is quit!")


def net_run(arg):
    global g_client
    global g_flag_quit
    while True:
        # 连接服务端
        println("client is waiting for connecting...")
        println("serv_ip=", g_serv_host, ",serv_port=", g_serv_port)
        port = int(g_serv_port)
        try:
            g_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            g_client.connect((g_serv_host, port))
            println("client is linked.")
            break
        except Exception as e:
            println("client error happen:", str(e))
            time.sleep(1)

    # send_str = "#i-am-client#"
    # g_client.send(send_str.encode("utf-8"))
    # g_client.setblocking(0)  # 0=NoneBlock
    total = 0
    while True:
        if g_flag_quit == True:
            break
        msg = g_client.recv(1024)
        len_recv = len(msg)
        # 接收服务端返回的数据，需要解码
        if len_recv > 0:
            total += len_recv
            println("sock_recv:", msg.hex())
            println("S_len:", len_recv, " all:", total)
            uart_send(msg)
        else:
            println("client is disconnected.")
            break
        time.sleep(0.02)
    # 关闭客户端
    g_client.close()
    g_flag_quit = True
    println("client is quit!")


def start_net_to_uart():
    global g_serial
    g_serial = serial.Serial(g_uart_name, 9600, timeout=0.05)
    td1 = threading.Thread(target=serial_run, args=(1,))
    td1.start()
    td2 = threading.Thread(target=net_run, args=(2,))
    td2.start()


if __name__ == "__main__":
    start_net_to_uart()
